//! 二进制代码生成器
//! 
//! 将 AST 转换为可执行的二进制代码
//! 支持多架构：通过 InstructionEncoder trait 抽象
//! 支持两遍扫描：第一遍收集标签，第二遍生成代码

use crate::ast::*;
use crate::error::Result;
use crate::instruction::InstructionEncoder;
use crate::symbol::SymbolTable;

/// 代码生成器（支持多架构）
pub struct CodeGenerator {
    encoder: Box<dyn InstructionEncoder>,
    binary: Vec<u8>,
    symbol_table: SymbolTable,
}

impl CodeGenerator {
    /// 创建新的代码生成器（使用指定的编码器）
    pub fn with_encoder(encoder: Box<dyn InstructionEncoder>) -> Self {
        Self {
            encoder,
            binary: Vec::new(),
            symbol_table: SymbolTable::new(),
        }
    }
    
    /// 创建新的代码生成器（8086模式，向后兼容）
    pub fn new() -> Self {
        use crate::instruction::Encoder8086;
        Self::with_encoder(Box::new(Encoder8086::new()))
    }

    /// 生成二进制代码（两遍扫描）
    pub fn generate(&mut self, program: &Program) -> Result<Vec<u8>> {
        // 第一遍：收集标签定义
        self.collect_labels(program)?;
        
        // 第二遍：生成代码
        self.generate_code(program)?;
        
        // 检查是否有未定义的标签
        self.symbol_table.check_undefined_symbols()?;
        
        Ok(self.binary.clone())
    }

    /// 第一遍扫描：收集标签定义
    fn collect_labels(&mut self, program: &Program) -> Result<()> {
        self.symbol_table = SymbolTable::new();
        
        for statement in &program.statements {
            match statement {
                Statement::Label(label_name, line) => {
                    // 定义标签地址为当前代码位置（第一遍扫描，不允许重复定义）
                    self.symbol_table.define_label(label_name.clone(), *line, false)?;
                }
                Statement::DataDefinition(data_def) => {
                    // 如果有标签，定义数据标签地址（第一遍扫描，不允许重复定义）
                    if let Some(ref label) = data_def.label {
                        self.symbol_table.define_label(label.clone(), data_def.line, false)?;
                    }
                    
                    // 计算数据大小
                    let size = self.calculate_data_size(data_def);
                    self.symbol_table.advance_address(size);
                }
                Statement::Instruction(instruction) => {
                    // 计算指令长度（用于地址计算）
                    let size = self.encoder.estimate_instruction_size(instruction)?;
                    self.symbol_table.advance_address(size);
                }
                Statement::Comment(_) => {
                    // 注释不占用地址
                }
            }
        }
        
        Ok(())
    }

    /// 第二遍扫描：生成代码
    fn generate_code(&mut self, program: &Program) -> Result<()> {
        self.binary.clear();
        self.symbol_table.reset_address(); // 重置地址计数器
        
        for statement in &program.statements {
            match statement {
                Statement::Label(label_name, line) => {
                    // 定义标签地址为当前代码位置（第二遍扫描，允许更新地址）
                    self.symbol_table.define_label(label_name.clone(), *line, true)?;
                }
                Statement::DataDefinition(data_def) => {
                    // 如果有标签，定义数据标签地址（第二遍扫描，允许更新地址）
                    if let Some(ref label) = data_def.label {
                        self.symbol_table.define_label(label.clone(), data_def.line, true)?;
                    }
                    
                    // 生成数据代码
                    let bytes = self.generate_data_bytes(data_def)?;
                    self.binary.extend_from_slice(&bytes);
                    self.symbol_table.advance_address(bytes.len());
                }
                Statement::Instruction(instruction) => {
                    // 生成指令代码（处理标签引用）
                    let bytes = self.encode_instruction_with_labels(instruction)?;
                    self.binary.extend_from_slice(&bytes);
                    self.symbol_table.advance_address(bytes.len());
                }
                Statement::Comment(_) => {
                    // 注释不生成代码
                }
            }
        }
        
        Ok(())
    }

    /// 编码指令（处理标签引用）
    fn encode_instruction_with_labels(&self, instruction: &Instruction) -> Result<Vec<u8>> {
        // 将标签引用转换为地址
        let mut operands = instruction.operands.clone();
        for operand in &mut operands {
            if let Operand::Label(label_name) = operand {
                let target_addr = self.symbol_table.get_label_address(label_name)?;
                let current_addr = self.symbol_table.current_address();
                
                // 根据指令类型确定指令大小（使用编码器的方法）
                // 注意：对于跳转指令，Label 操作数的大小与 Immediate(rel16) 相同
                // - JMP label: 3 字节（操作码 1 + rel16 2）
                // - CALL label: 3 字节（操作码 1 + rel16 2）
                // - 条件跳转: 2 或 3 字节（取决于偏移范围）
                // estimate_instruction_size 已经正确处理了 Label 操作数的大小估算
                let instruction_size = self.encoder.estimate_instruction_size(instruction)?;
                
                let offset = (target_addr as i64) - (current_addr as i64) - (instruction_size as i64);
                
                // 根据指令类型检查偏移范围（使用编码器的方法）
                if let Some((min_offset, max_offset)) = self.encoder.get_jump_offset_range(&instruction.name) {
                    if offset < min_offset || offset > max_offset {
                        return Err(crate::error::AssemblerError::CodeGenError {
                            message: format!(
                                "{} 偏移超出范围: {} 字节（标签: {}，支持范围: {} 到 {} 字节）",
                                instruction.name, offset, label_name, min_offset, max_offset
                            ),
                        });
                    }
                }
                
                *operand = Operand::Immediate(offset);
            }
        }
        
        // 使用修改后的操作数编码指令
        self.encoder.encode_instruction(&instruction.name, &operands)
    }

    /// 计算字符串的字节大小（与生成逻辑一致）
    /// "￥"字符被替换为1个字节的0（自定义字符串结尾符）
    fn calculate_string_size(s: &str) -> usize {
        let mut size = 0;
        for ch in s.chars() {
            if ch == '￥' {
                size += 1;  // "￥"被替换为1个字节的0（自定义字符串结尾符）
            } else if ch.is_ascii() {
                size += 1;
            } else {
                // 对于非ASCII字符，使用UTF-8编码长度
                let mut utf8_bytes = [0u8; 4];
                size += ch.encode_utf8(&mut utf8_bytes).len();
            }
        }
        size
    }

    /// 计算数据定义的大小（新增）
    fn calculate_data_size(&self, data_def: &DataDefinition) -> usize {
        let mut size = 0;
        for value in &data_def.values {
            match value {
                DataValue::Immediate(_) => {
                    match data_def.data_type {
                        DataType::Byte => size += 1,
                        DataType::Word => size += 2,
                    }
                }
                DataValue::String(s) => {
                    size += Self::calculate_string_size(s);
                }
            }
        }
        size
    }

    /// 生成数据定义的二进制代码（新增）
    fn generate_data_bytes(&self, data_def: &DataDefinition) -> Result<Vec<u8>> {
        let mut bytes = Vec::new();
        
        for value in &data_def.values {
            match value {
                DataValue::Immediate(imm) => {
                    match data_def.data_type {
                        DataType::Byte => {
                            if *imm < -128 || *imm > 255 {
                                return Err(crate::error::AssemblerError::CodeGenError {
                                    message: format!("字节值超出范围: {} (范围: -128 到 255)", imm),
                                });
                            }
                            // 类型转换说明：
                            // - 对于负数（-128 到 -1），Rust 的 `as u8` 会进行模运算
                            //   例如：-1 as u8 = 255, -128 as u8 = 128
                            // - 对于正数（0 到 255），直接转换
                            // - 由于已经检查了范围，转换是安全的
                            bytes.push(*imm as u8);
                        }
                        DataType::Word => {
                            if *imm < -32768 || *imm > 65535 {
                                return Err(crate::error::AssemblerError::CodeGenError {
                                    message: format!("字值超出范围: {} (范围: -32768 到 65535)", imm),
                                });
                            }
                            // 类型转换说明：
                            // - 对于负数（-32768 到 -1），转换为 u16 会进行模运算
                            //   例如：-1 as u16 = 65535, -32768 as u16 = 32768
                            // - 对于正数（0 到 65535），直接转换
                            // - 由于已经检查了范围，转换是安全的
                            let word = *imm as u16;
                            // 小端序：低字节在前，高字节在后
                            bytes.push(word as u8);           // 低字节
                            bytes.push((word >> 8) as u8);    // 高字节
                        }
                    }
                }
                DataValue::String(s) => {
                    // 字符串按字节存储，将"￥"字符替换为0字节（自定义字符串结尾符）
                    // 逻辑必须与 calculate_string_size 完全一致
                    for ch in s.chars() {
                        if ch == '￥' {
                            bytes.push(0u8);  // "￥"被替换为1个字节的0（自定义字符串结尾符）
                        } else if ch.is_ascii() {
                            bytes.push(ch as u8);
                        } else {
                            // 对于非ASCII字符，使用UTF-8编码
                            let mut utf8_bytes = [0u8; 4];
                            let utf8_len = ch.encode_utf8(&mut utf8_bytes).len();
                            bytes.extend_from_slice(&utf8_bytes[..utf8_len]);
                        }
                    }
                }
            }
        }
        
        Ok(bytes)
    }
}

impl Default for CodeGenerator {
    fn default() -> Self {
        Self::new()
    }
}

